package com.pro.framework.api.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;

public class DateTimeSplitter {

    /**
     * 将时间范围按指定时间单位和间隔切割
     *
     * @param start    开始时间
     * @param end      结束时间
     * @param interval 间隔数量
     * @param timeUnit 时间单位
     * @return 时间区间列表
     */
    public static List<TimeRange> splitByTimeUnit(LocalDateTime start, LocalDateTime end,
                                                  Number interval, ChronoUnit timeUnit) {
        if (interval == null) {
            return Collections.singletonList(new TimeRange(start, end));
        }
        long intervalValue = interval.longValue();
        // 参数校验
        Objects.requireNonNull(start, "开始时间不能为null");
        Objects.requireNonNull(end, "结束时间不能为null");
        Objects.requireNonNull(timeUnit, "时间单位不能为null");
        if (intervalValue <= 0) {
            throw new IllegalArgumentException("间隔数量必须大于0");
        }
        if (start.isAfter(end)) {
            throw new IllegalArgumentException("开始时间不能晚于结束时间");
        }

        List<TimeRange> result = new ArrayList<>();
        LocalDateTime currentStart = start;

        while (currentStart.isBefore(end)) {
            // 计算当前区间的结束时间
            LocalDateTime currentEnd = currentStart.plus(intervalValue, timeUnit);

            // 如果计算出的结束时间超过了总体结束时间，则使用总体结束时间
            if (currentEnd.isAfter(end)) {
                currentEnd = end;
            }

            result.add(new TimeRange(currentStart, currentEnd));

            // 移动到下一个区间的开始时间（当前结束时间 + 1纳秒）
            currentStart = currentEnd.plusNanos(1);

            // 如果下一个区间的开始时间已经超过结束时间，则退出循环
            if (!currentStart.isBefore(end)) {
                break;
            }
        }

        return result;
    }

    /**
     * 按天数间隔切割的便捷方法
     */
    public static List<TimeRange> splitByDays(LocalDateTime start, LocalDateTime end, Number days) {
        return splitByTimeUnit(start, end, days, ChronoUnit.DAYS);
    }

    /**
     * 按小时间隔切割的便捷方法
     */
    public static List<TimeRange> splitByHours(LocalDateTime start, LocalDateTime end, Number hours) {
        return splitByTimeUnit(start, end, hours, ChronoUnit.HOURS);
    }

//    /**
//     * 专门处理2天间隔的便捷方法
//     */
//    public static List<TimeRange> splitByTwoDays(LocalDateTime start, LocalDateTime end) {
//        return splitByDays(start, end, 2L);
//    }

    // ========== Date版本的重载方法 ==========

    public static List<TimeRange> splitByTimeUnit(Date start, Date end,
                                                  Number interval, ChronoUnit timeUnit) {
        LocalDateTime startLdt = LocalDateTimeUtil.of(start);
        LocalDateTime endLdt = LocalDateTimeUtil.of(end);
        return splitByTimeUnit(startLdt, endLdt, interval, timeUnit);
    }

    public static List<TimeRange> splitByDays(Date start, Date end, Number days) {
        return splitByTimeUnit(start, end, days, ChronoUnit.DAYS);
    }

    public static List<TimeRange> splitByHours(Date start, Date end, Number hours) {
        return splitByTimeUnit(start, end, hours, ChronoUnit.HOURS);
    }

//    public static List<TimeRange> splitByTwoDays(Date start, Date end) {
//        return splitByDays(start, end, 2L);
//    }

    /**
     * 时间区间记录类
     */
    @Data
    @AllArgsConstructor
    public static class TimeRange {
        private LocalDateTime start;
        private LocalDateTime end;
    }

}